home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / pnl001.arc / PNL001.TXT < prev   
Text File  |  1991-04-28  |  25KB  |  1,057 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.                             
  14.                                                      
  15.                                                                  
  16.                                                                  
  17.                                 ////////    //    //    //   
  18.                                //    //    ///   //    //    
  19.                               //    //    ////  //    //     
  20.                              ////////    // // //    //      
  21.                             //          //  ////    //       
  22.                            //          //   ///    //          
  23.                           //          //    //    ///////    
  24.                                                                  
  25.                                                                  
  26.                                                              
  27.                                                             
  28.                                                             
  29.                                   Pascal NewsLetter         
  30.                                        Issue #1              
  31.                                       May, 1990             
  32.                                                             
  33.                                                             
  34.                                   Editor: Pete Davis         
  35.                                                             
  36.                                                             
  37.                                                             
  38.                                                             
  39.                                                             
  40.                                                             
  41.                                                             
  42.                                                             
  43.                                                             
  44.                                                             
  45.                                                             
  46.                                                             
  47.                                                             
  48.                                                             
  49.                                                             
  50.                                                                 
  51.                     The Programmer's Forum BBS is the home of
  52.                     PNL. It can be reached in Washington, DC at
  53.                     (202)966-3647. Information is available 
  54.                     through the following locations:        
  55.                                                             
  56.                     FidoNet: Pete Davis@1:109/138           
  57.                     GEnie: PDAVIS5                          
  58.                     BitNet: HJ647C@GWUVM & UE356C@GWUVM     
  59.                                                                 
  60.                                                             
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.                                                             
  74.                                                             
  75.                                                             
  76.                                 Table Of Contents           
  77.                                                             
  78.                                                             
  79.                                                             
  80.           Introduction .......................... Page 3  (Pete Davis)
  81.           Generic Structures in Turbo Pascal .... Page 5  (Pete Davis)
  82.           Turbo Pascal Program Optimization ..... Page 10 (Pete Davis)
  83.           Conclusion ............................ Page 16 (Pete Davis)
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.                                                
  107.           Turbo Pascal is a Registered Tradmark of Borland
  108.           International.
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.                                   Introduction
  140.  
  141.  
  142.  
  143.                Well, welcome to the  premier issue of the Pascal  News
  144.  
  145.           Letter. Since this is  the first issue, it's  important that
  146.  
  147.           the purpose of  the newsletter be  stated. I run a  bulletin
  148.  
  149.           board in Washington, and I often come across newsletters and
  150.  
  151.           magazine. I  have yet  to  find any  geared towards  Pascal,
  152.  
  153.           though.  (Save  for a  few  which  aren't really  worthy  of
  154.  
  155.           mention.)  Because  I  use  Pascal  quite  often,  I  became
  156.  
  157.           frustrated that there  wasn't a free source  of information.
  158.  
  159.           Sure, I could  go out and buy some magazines that are Pascal
  160.  
  161.           oriented, but  when there  are newsletters  like CNews,  and
  162.  
  163.           MicroCornucopia  about,  why should  I  have to  bother with
  164.  
  165.           that? There should be a Pascal oriented one. Well, now there
  166.  
  167.           is.  
  168.  
  169.                My  main purpose  with the newsletter  is to  provide a
  170.  
  171.           good place for the solutions to common problems. Many people
  172.  
  173.           have  questions regarding pascal and have  a lot of problems
  174.  
  175.           getting those questions  answered. There are  also a lot  of
  176.  
  177.           people  with  fantastic  concepts and  ideas  waiting  to be
  178.  
  179.           passed around, but  no means to  pass it around. There  will
  180.  
  181.           now be a  way. Because this is the first issue, all articles
  182.  
  183.           are written by  myself, this is also  why it might be  a bit
  184.  
  185.           skimpy. Hopefully this will improve  with further issues. It
  186.  
  187.           is my  hope that people with interesting  ideas and concepts
  188.  
  189.           will  pass them  along  to me,  preferably  with an  article
  190.  
  191.  
  192.                                                                      3
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.           attached.
  206.  
  207.                Most of the  articles are geared towards  Turbo Pascal.
  208.  
  209.           This is not meant as a  limitation, however. Turbo Pascal is
  210.  
  211.           about as  standard as  the IBM  compatible pascal  compilers
  212.  
  213.           get. Many of the ideas will be portable to other versions of
  214.  
  215.           pascal, if possible.
  216.  
  217.                Like many of  you, I'm sure,  I'm a busy person.  Doing
  218.  
  219.           this newsletter will  take a significant amount  of my time,
  220.  
  221.           but from  this, I would like  to explain my articles  a bit.
  222.  
  223.           Complete pieces of  code are  not always provided.  Instead,
  224.  
  225.           partial pieces of code  and algorithms will make up  a large
  226.  
  227.           part of my articles. (I am only  speaking for myself and not
  228.  
  229.           others, who in  the future may  provide full pieces of  code
  230.  
  231.           for the newsletter.) My  purpose is to get the  concepts and
  232.  
  233.           ideas across and  let you, the  reader, implement them in  a
  234.  
  235.           way that suits you.
  236.  
  237.                I am  very fond of  feedback, and  would love to  get a
  238.  
  239.           message  now and  then  about what  you, the  reader, thinks
  240.  
  241.           about PNL,  and what you would like to see in future issues.
  242.  
  243.           Please feel  free to  send your  feedback, suggestions,  and
  244.  
  245.           articles,  especially,  to any  of  the above  addresses. As
  246.  
  247.           editor,  you  may  expect several  topical  changes  to your
  248.  
  249.           articles, but nothing major.
  250.  
  251.                                               Pete Davis
  252.  
  253.                                               Editor
  254.  
  255.  
  256.  
  257.  
  258.                                                                      4
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.                        Generic Structures in Turbo Pascal
  272.  
  273.             
  274.  
  275.                I have to  thank my  current professor, Raymond  Thomas
  276.  
  277.           for the ideas and concepts covered in this article. Although
  278.  
  279.           I had thought only  a bit about the generic  structures, his
  280.  
  281.           class forced me too look at them more closely. 
  282.  
  283.                The  structure  provided  in our  class  was  a generic
  284.  
  285.           linked list, but  the idea can  be carried out into  several
  286.  
  287.           other implementations. The  idea is to  have a unit of  code
  288.  
  289.           that  can  be re-used  for  different  types  of  data.  For
  290.  
  291.           example,  one  could  write  a   unit  that  performs  stack
  292.  
  293.           operations of POP and PUSH, but have it be able to work with
  294.  
  295.           integers, strings, real  numbers, or  even records. This  is
  296.  
  297.           very useful if you  want to write units and  distribute them
  298.  
  299.           in the public  domain or  as shareware, and  have people  be
  300.  
  301.           able to use them for themselves. Such procedures as  generic
  302.  
  303.           linked  lists, stacks,  queues,  B-Trees, sorting  routines,
  304.  
  305.           etc...
  306.  
  307.                There are several  features of  Turbo Pascal that  make
  308.  
  309.           this possible. Among them is the untyped pointer, the SizeOf
  310.  
  311.           function, the Move, GetMem, and  FreeMem procedures, and the
  312.  
  313.           untyped parameter. 
  314.  
  315.                The heart of any  generic structure is going to  be the
  316.  
  317.           source   of  information   about  the   structure  and   the
  318.  
  319.           information holder. In  our example, it  is going to be  the
  320.  
  321.           head of the stack:
  322.  
  323.  
  324.                                                                      5
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.           type
  341.             StackPtr = ^StackItem;
  342.             StackItem = record
  343.               NextItem : StackPtr;
  344.               DataItem : pointer;
  345.             end;
  346.  
  347.             HeadPtr = ^Header;
  348.             Header = record
  349.               Size  : word;
  350.               Top   : StackPtr;
  351.             end;
  352.  
  353.  
  354.                Now for a bit of  an explanation of our stack. For  the
  355.  
  356.           most part,  it follows  the standard  structure of  a linked
  357.  
  358.           list implementation  of a  stack. The  main differences  one
  359.  
  360.           notices are the Size (in the Header record) and DataItem (in
  361.  
  362.           the StackItem record).  Size is the  size of the data  items
  363.  
  364.           being  placed in  the stack.  This is  where  Turbo Pascal's
  365.  
  366.           SizeOf function comes  in handy. To  show how this works,  I
  367.  
  368.           will present the StackInit procedure.
  369.  
  370.  
  371.  
  372.           procedure InitStack(var H_Ptr : Header; ItemSize : word);
  373.  
  374.           begin
  375.             New(H_Ptr);
  376.             H_Ptr^.Size := ItemSize;
  377.             H_Ptr^.Top  := nil;
  378.           end;
  379.  
  380.  
  381.                A typical call to the InitStack procedure would be like
  382.  
  383.           this:
  384.  
  385.           InitStack(H, SizeOf(MyData));
  386.  
  387.  
  388.  
  389.  
  390.                                                                      6
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.                Now, let's examine the  StackItem record. The  DataItem
  404.  
  405.           field provides only a generic pointer. Here is where the big
  406.  
  407.           difference between the  Generic Data Structure and  the Pre-
  408.  
  409.           Defined Data Structure  shows itself. Because DataItem  is a
  410.  
  411.           Generic pointer, it has  no size associated with it.  One is
  412.  
  413.           unable  to  use  the  New and  Dispose  procedures  for  the
  414.  
  415.           individual  data items  in the stack.  Instead, the  New and
  416.  
  417.           Dispose procedures are used to handle the StackItem records,
  418.  
  419.           while  the GetMem and FreeMem procedures  are used to handle
  420.  
  421.           the data  in those StackItem records. Here  is a sample of a
  422.  
  423.           Push procedure:
  424.  
  425.  
  426.           procedure Push(H_Ptr : Header; var Data);
  427.  
  428.           { Notice that Data is an un-typed variable }
  429.  
  430.           var
  431.             ANode : StackPtr;  { Our temporary node }
  432.  
  433.           begin
  434.             { Allocate memory for the node itself. }
  435.             New(ANode);  
  436.  
  437.             { Allocate space for the user's data and set a 
  438.               pointer to it in ANode.                      }
  439.             GetMem(ANode^.DataItem, H_Ptr^.Size);
  440.  
  441.             { Since it's a stack, and it's the newest item,
  442.               have it point to the previous top of the stack }
  443.             ANode^.NextItem := H_Ptr^.Top;
  444.  
  445.             { and have the new top point to our new node }
  446.             H_Ptr^.Top      := ANode;
  447.  
  448.             { Now physically move the data from it's current
  449.               unprotected space, and into the space acquired for it.}
  450.             Move(Data, ANode^.NextItem^, H_Ptr^.Size);
  451.           end;
  452.  
  453.  
  454.  
  455.  
  456.                                                                      7
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.                Ok, so now we have our Push procedure. The comments are
  470.  
  471.           a little  thick, but  they can be  removed to  make it  look
  472.  
  473.           nicer.  I don't  really think  I need  to go  into  too much
  474.  
  475.           discussion of the operations in the  Push procedure, for the
  476.  
  477.           most part they are pretty straight  forward. I would like to
  478.  
  479.           caution about  the use of  the Move procedure,  however. You
  480.  
  481.           need  to know exactly where you  are moving your data to and
  482.  
  483.           from. It  might take a little  work to get  exactly what you
  484.  
  485.           want. 
  486.  
  487.                Now,  what  good  is a  stack  that  you  can only  put
  488.  
  489.           information into, and not get any back? Not much, so here is
  490.  
  491.           the Pop procedure:
  492.  
  493.  
  494.  
  495.           procedure Pop(H_Ptr : Header; var Data);
  496.  
  497.           { It would be nice to have the Pop procedure be a function 
  498.             returning the value, but we can't return an untyped  
  499.           value                                                   }
  500.  
  501.           var
  502.             ANode : StackPtr;   { Our temporary node }
  503.  
  504.           begin
  505.             { First, make sure we're working with a
  506.               non-empty stack!                      }
  507.             if not StackEmpty(H_Ptr) then
  508.               begin
  509.               
  510.                 { Set ANode to the top of the list }
  511.                 ANode := H_Ptr^.Top;
  512.  
  513.                 { Have the Top now point to the second item
  514.                  in the list                                  }
  515.                 H_Ptr^.Top := ANode^.NextItem;
  516.  
  517.                 { Move the contents of the data to the user's
  518.                   variable.                                   }
  519.                 Move(ANode^.DataItem^, Data, H_Ptr^.Size);
  520.  
  521.  
  522.                                                                      8
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.                 { Return our data's memory and our node
  536.                   itself to the heap.                         }
  537.                 FreeMem(ANode^.DataItem, H_Ptr^.Size);
  538.                 Dispose(ANode);
  539.               end
  540.             else
  541.               ... Error routine goes here ...
  542.           end;
  543.             
  544.  
  545.                Well, that just about covers  the basics of our generic
  546.  
  547.           data structure. I  left out some  of the routines, but  they
  548.  
  549.           should be  pretty easy to  add. For example,  the EmptyStack
  550.  
  551.           function would return a boolean value of true  if H_Ptr^.Top
  552.  
  553.           was nil. So, I'll  leave the rest of it to you.  There are a
  554.  
  555.           multitude  of  possibilities  and  uses   for  generic  data
  556.  
  557.           structures.  It's just  one more  way to make  your routines
  558.  
  559.           'user friendly'.
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.                                                                      9
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.                         Turbo Pascal Program Optimization
  602.  
  603.  
  604.  
  605.                This   article  will   cover  a   portion  of   program
  606.  
  607.           optimization in Turbo Pascal.  I say it  covers a portion of
  608.  
  609.           optimization  only  because  optimization  is  such  a  vast
  610.  
  611.           subject that it would be impossible to cover completely in a
  612.  
  613.           single  article. I  also gear it  towards Turbo  Pascal, but
  614.  
  615.           most  of  the tips  here  will  apply to  almost  all pascal
  616.  
  617.           compilers.
  618.  
  619.  
  620.  
  621.           WHERE TO OPTIMIZE:
  622.  
  623.  
  624.  
  625.                The  most  important step  in  optimizing a  program is
  626.  
  627.           deciding where to  optimize. A good programmer  is compelled
  628.  
  629.           to  optimize  as he/she  writes  the  code. This  is  a good
  630.  
  631.           programming  practice,  which  once  you  know most  of  the
  632.  
  633.           important optimizations secrets, is easy to implement as you
  634.  
  635.           code. A big  problem occurs when  you try to optimize  after
  636.  
  637.           writing the  code. The reason this is a problem is one tends
  638.  
  639.           to try to  optimize every  bit of code.  This is  incredibly
  640.  
  641.           time  consuming   and   usually   results   in   only   mild
  642.  
  643.           improvements. Knowing where to optimize, however, can save a
  644.  
  645.           lot of time in coding and a lot of time in execution. 
  646.  
  647.                There are a lot of  places where optimization will make
  648.  
  649.           huge improvements in code speed. Learning to recognize where
  650.  
  651.           your program is  spending it's  time is easy  once you  know
  652.  
  653.  
  654.                                                                     10
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.           what to look  for. First of  all, loops! Loops should  stick
  668.  
  669.           out like  a sore  thumb when  optimizing a  program. A  user
  670.  
  671.           recently  came into  work  with a  program  that he  thought
  672.  
  673.           wasn't working. He  complained that  he had let  it run  for
  674.  
  675.           fifteen minutes and  still didn't get his  results. Although
  676.  
  677.           his program was  only about 20 lines of code,  it would take
  678.  
  679.           at least 2 hours to run. Why? He had 4  loops. Each loop was
  680.  
  681.           inside another loop.  That adds up pretty  quickly. Each one
  682.  
  683.           looped 100 times. Now, let's figure  out how many loops that
  684.  
  685.           is: 100 * 100 * 100 * 100 = 100,000,000 loops total. To make
  686.  
  687.           things worse, he  had some pretty heavy  calculations inside
  688.  
  689.           the inner loop.  Ok, so  loops are definitely  one place  to
  690.  
  691.           look for optimization.
  692.  
  693.                Don't just look at loops, though, look at what's inside
  694.  
  695.           a loop. Sometimes redundant data is placed inside loops that
  696.  
  697.           can  be taken out of the loop. Declaring a variable inside a
  698.  
  699.           loop that is always the same: 
  700.  
  701.           example ->
  702.  
  703.           for x:=1 to 80 do
  704.             begin
  705.               y:=1
  706.               gotoxy(x,y);
  707.               write('x');
  708.             end;
  709.  
  710.  
  711.                Here  we have the  variable y being  declared 80 times,
  712.  
  713.           while it never  changes. This  can be fixed  by declaring  y
  714.  
  715.           before  entering into  the  loop.  This  is a  very  obvious
  716.  
  717.           example, but sometimes it isn't quite so obvious.
  718.  
  719.  
  720.                                                                     11
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.           SPEED vs. SIZE
  734.  
  735.  
  736.  
  737.                Optimization really  covers two areas: Speed  and Size.
  738.  
  739.           Unfortunately, optimizing for one usually ends up making the
  740.  
  741.           other  worse.  There  are  some  exceptions,  however,  like
  742.  
  743.           passing variable  parameters as opposed  to value parameters
  744.  
  745.           as we'll  cover later.  Speed  is almost  always of  primary
  746.  
  747.           importance and I will usually emphasize it. 
  748.  
  749.  
  750.  
  751.           VALUE vs. VARIABLE PARAMETERS
  752.  
  753.  
  754.  
  755.                When writing procedures or functions, there  is usually
  756.  
  757.           a  little  thought about  whether to  use variable  or value
  758.  
  759.           parameters. The normal train  of thought is that you  pass a
  760.  
  761.           variable parameter  only if  that value  will change  in the
  762.  
  763.           procedure or  function. Now lets look at  what actually goes
  764.  
  765.           on behind the scenes. When a parameter is a value parameter,
  766.  
  767.           there are  no changes made  to the  actual variable  itself.
  768.  
  769.           This means  that an exact copy  of the variable  needs to be
  770.  
  771.           made in memory. With  a character or byte value,  this isn't
  772.  
  773.           real  significant, but  what if  you're passing an  array of
  774.  
  775.           1000 integers. That means an exact  copy of 2000 bytes needs
  776.  
  777.           to be copied in memory. This not only takes time but it also
  778.  
  779.           takes up quite a bit of memory. If your routine is recursive
  780.  
  781.           or  occurs  inside a  loop,  you  are looking  at  a serious
  782.  
  783.           decrease in speed and a huge increase in memory use. One way
  784.  
  785.  
  786.                                                                     12
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.           to  repair  this  is to  pass  variable  parameters whenever
  800.  
  801.           possible. There are some times when it is impossible to pass
  802.  
  803.           a  variable parameter.  In these  cases you'll be  forced to
  804.  
  805.           pass a value parameters. 
  806.  
  807.                For   those   unfamiliar   with  variable   and   value
  808.  
  809.           parameters, here are two examples:
  810.  
  811.  
  812.  
  813.           procedure ShowIt1(S : string);
  814.  
  815.           begin
  816.             write(S);
  817.           end;
  818.  
  819.           procedure ShowIt2(var S : string);
  820.  
  821.           begin
  822.             write(S);
  823.           end;
  824.  
  825.                The first procedure,  ShowIt1, uses a  value parameter.
  826.  
  827.           This means that an exact copy of the string S has to be made
  828.  
  829.           in  memory. Since a string can be up to 255 characters, this
  830.  
  831.           can add up.
  832.  
  833.                The second procedure uses a variable parameter. Instead
  834.  
  835.           of passing a complete copy of the variable, a pointer to the
  836.  
  837.           string S  itself is  passed. Since  this pointer  is only  4
  838.  
  839.           bytes long, you can make a very significant improvement.
  840.  
  841.  
  842.  
  843.           COMPILER DIRECTIVES
  844.  
  845.  
  846.  
  847.                When  testing a  new program, it  is very  important to
  848.  
  849.           have  compiler  options, such  as  range checking  and stack
  850.  
  851.  
  852.                                                                     13
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.           checking active. Truth  is, though,  that these options  add
  866.  
  867.           quite a  bit  of time-consuming  code to  your programs.  Of
  868.  
  869.           course, it is good  to have them in  when writing the  first
  870.  
  871.           copy of your program, but when compiling a final version, it
  872.  
  873.           is a good idea  to disable these options. The  results are a
  874.  
  875.           significant increase in speed, and a nice cut in the size of
  876.  
  877.           the final program.
  878.  
  879.  
  880.  
  881.           IF/THEN vs. IF/THEN/ELSE vs. CASE
  882.  
  883.  
  884.  
  885.                The  last point of  optimization that  I will  cover in
  886.  
  887.           this issue is the decision structures. Here is a short piece
  888.  
  889.           of code. The variable C is type char:
  890.  
  891.  
  892.  
  893.           1>  ---- IF/THEN ----
  894.           if C = 'A' then writeln('You Win!');
  895.           if C = 'B' then writeln('You Lose!');
  896.           if C = 'C' then writeln('Tie Game!');
  897.  
  898.           2> ---- IF/THEN/ELSE ----
  899.           if C = 'A' then writeln('You Win!') else
  900.           if C = 'B' then writeln('You Lose!') else
  901.           if C = 'C' then writeln('Tie Game!');
  902.  
  903.           3> ---- CASE ----
  904.           case C of
  905.             'A' : writeln('You Win!');
  906.             'B' : writeln('You Lose!');
  907.             'C' : writeln('Tie Game);
  908.           end;
  909.  
  910.  
  911.           The first example is  the slowest of  the three. It is  also
  912.  
  913.           the  least  clear  of the  code.  It  is  rarely a  required
  914.  
  915.           structure, and can usually be  replace by the more efficient
  916.  
  917.  
  918.                                                                     14
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.           IF/THEN/ELSE structure.  When possible,  though, one  should
  932.  
  933.           use the CASE structure. It is  the best method for something
  934.  
  935.           like  the  above  coding. It  is  faster  and  requires less
  936.  
  937.           memory.
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.                                                                     15
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.  
  997.                                    Conclusion
  998.  
  999.  
  1000.  
  1001.                Well, like I  said in the  beginning, this is a  little
  1002.  
  1003.           skimpy, but it  is the first  issue. I hope  to have a  more
  1004.  
  1005.           full second  issue.  If you  have  some good  ideas,  please
  1006.  
  1007.           submit them. Since this is the end of the spring semester, I
  1008.  
  1009.           will  be  looking  at  quite  a  bit  more  time  as  summer
  1010.  
  1011.           approaches.  So,  with my  extra  time and,  hopefully, your
  1012.  
  1013.           submissions,  the second and later issues  will be larger. I
  1014.  
  1015.           am  also planning on including  complete pieces of code with
  1016.  
  1017.           the newsletter itself.
  1018.  
  1019.                Please send your submissions to the addresses provided.
  1020.  
  1021.           I hope you enjoy this and I look forward to your comments!
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.                                                                     16
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.